package com.redijedi.tapestry.components;

import java.util.Queue;

import org.apache.tapestry.MarkupWriter;
import org.apache.tapestry.annotations.AfterRender;
import org.apache.tapestry.annotations.BeforeRenderTemplate;
import org.apache.tapestry.annotations.BeginRender;
import org.apache.tapestry.annotations.Environmental;
import org.apache.tapestry.annotations.Parameter;
import org.apache.tapestry.annotations.SetupRender;
import org.apache.tapestry.services.Heartbeat;

import com.redijedi.tapestry.ITreeNodeModel;
import com.redijedi.tapestry.internal.tree.TreeNodeVisitor;
import com.redijedi.tapestry.internal.tree.TreeRenderer;
import com.redijedi.tapestry.internal.tree.TreeRendererCommand;
import com.redijedi.tapestry.internal.tree.TreeRendererCommandNodeSet;

/**
 * @author torr
 * 
 */
public class Tree<T> {

	@Environmental
	private Heartbeat heartbeat;

	@Parameter(required = true, defaultPrefix = "prop")
	private ITreeNodeModel<T> _model;

	@SuppressWarnings("unused")
	@Parameter(defaultPrefix = "prop")
	private T _value;

	private Queue<TreeRendererCommandNodeSet> _commandQueue;

	private TreeRenderer _renderer;

	private TreeRendererCommandNodeSet _currentCommand;

	@SetupRender
	boolean setup(MarkupWriter writer) {
		// traverse the model to get the command queue sequence
		TreeNodeVisitor visitor = new TreeNodeVisitor();
		_model.accept(visitor);
		_commandQueue = visitor.getRendererCommands();

		_renderer = new TreeRenderer(writer);

		return true;
	}

	@BeginRender
	void begin() {
		_currentCommand = _commandQueue.poll();
		_renderer.write(_currentCommand);
		heartbeat.begin();
	}

	@SuppressWarnings("unchecked")
	@BeforeRenderTemplate
	boolean render() {
		if (_currentCommand.getCommand() == TreeRendererCommand.RENDER_BODY) {
			_value = (T) _currentCommand.getNode().getValue();
			return true;
		} else {
			return false;
		}
	}

	@AfterRender
	boolean after() {
		_currentCommand = _commandQueue.poll();
		_renderer.write(_currentCommand);
		heartbeat.end();
		if (_commandQueue.isEmpty()) {
			return true;
		} else {
			return false;
		}
	}

}
